// SearchForm组件，装载所有的formItem
import React, { Component, forwardRef } from 'react';
import { withRouter } from 'react-router';
import { Form, Switch, message } from 'antd';
import PropTypes from 'prop-types';
import UtilsHOC from './utils'
import { connect } from 'react-redux';
import { pub_getAllTableData, pub_isLoading, pub_searchCondition, pub_clearSelectedData } from '@/Redux/ActionTypes/public/BaseTable/publicActionCreator.js';
import _fetch from '@/Utils/Fetch.js';
import { downloadFileTemplate } from '@/Utils'
import _ from 'lodash';
import './index.css';

const mapStateToProps = (state, ownProps) => {
  return {
    pub_isLoading: state.baseTable.pub_isLoading, // 是否拿到表格数据的标识
    fixedConf: state.baseTable.fixedConf, // 分页条件
    allSearchCondition: state.baseTable.allSearchCondition, // 所有搜索的条件
    pub_allTableData: state.baseTable.pub_allTableData, // 获取表格所有数据
  }
}
const mapDispatchToProps = (dispatch) => {
  return (
    {
      getAllTableData(...rest) {
        return dispatch(pub_getAllTableData(...rest)); // 把获取到的表格所有数据发送到store
      },
      pub_changeisLoading(...rest) {
        return dispatch(pub_isLoading(...rest)); // 把标志是否获取表格数据的isLoading标识修改
      },
      pub_sendSearchCondition(...rest) {
        return dispatch(pub_searchCondition(...rest)); // 把搜索条件都发送到store
      },
      pub_clearSelectedData(...rest) {
        return dispatch(pub_clearSelectedData(...rest))
      }
    })
}

class SearchForm extends Component {
  formRef = React.createRef();
  constructor(props) {
    super(props)
    const { location: { pathname }, markName, setSearchState } = this.props;// 写在这里的目的是为了将来一个页面可能会有多个表单。 将来在这里改一下标识即pathname就可以
    this.markId = markName ? markName : pathname;
    this.state = {
      formItemList: [],
      // 用于判断是否为更多搜索
      setSearchState: setSearchState ?? false
    };
  }

  componentDidMount() {
    const { getInstance, allSearchCondition } = this.props;
    this.formRef.current.setFieldsValue(allSearchCondition[this.markId])
    if (typeof getInstance === 'function') {
      // 在这里把this暴露给父组件（Utils高阶组件），得以让其通过使用 this.pubFormRef 获取 PubForm 的方法
      getInstance(this);
    }
    this.createFormItems();// 需要拿到item的默认数据去发请求
    // 设置table的高度值
    const dom = document.documentElement
    if (sessionStorage.getItem('tableHeight') !== dom.clientHeight - 275) {
      // 如果宽度过低表格高度减小
      if (dom.clientWidth <= 1300) {
        sessionStorage.setItem('tableHeight', dom.clientHeight - 315)
      } else {
        sessionStorage.setItem('tableHeight', dom.clientHeight - 275)
      }
    }
    // 设置table样式
    if (dom.clientHeight >= 1080) {
      dom.style.setProperty('--fileicon-font-size', '49px')
      dom.style.setProperty('--table-file-img-width', '67px')
    } else if (dom.clientHeight <= 940) {
      dom.style.setProperty('--fileicon-font-size', '38px')
      dom.style.setProperty('--table-file-img-width', '53px')
    } else {
      dom.style.setProperty('--fileicon-font-size', '41px')
      dom.style.setProperty('--table-file-img-width', '58px')
    }
  }
  // 分页器改变时要主动去请求下一页表格数据
  // 拿到全部搜索条件请求搜索接口获取后台数据，请求到后台数据之后存到store里面
  handleSumbit = (searchValue) => {
    const { changeSearchLimit, pub_sendSearchCondition, pub_clearSelectedData, formItems: { ajaxConfig } } = this.props;
    let searchData = this.formRef.current.getFieldsValue() // 拿到搜索数据
    searchData = this.searchAddPagination(searchData, searchValue) // 增加分页条件
    searchData = changeSearchLimit(searchData) // 格式化搜索数据格式
    let copySearchData = _.cloneDeep(searchData);
    copySearchData.ajaxConfig = ajaxConfig; // 把ajaxConfig也一起发过去
    pub_sendSearchCondition(copySearchData, this.markId) // 把搜索条件发送到store
    // 搜索后，清空当前页面的选中数据
    pub_clearSelectedData(this.markId)
    this.returnAllTableData(searchData) // 将格式化后的搜索数据传给表格
    return searchData // 将格式化后的数据返回
  }

  /**
   * 该方法用于导出案卷/文件列表excel
   *
   */
  handlePrint = async () => {
    const { changeSearchLimit } = this.props;
    let searchData = this.formRef.current.getFieldsValue() // 拿到搜索数据
    searchData = changeSearchLimit(searchData) // 格式化搜索数据格式
    const ajaxConfig = {
      // url: dossierUrl.printDirectory,
      data: searchData,
      type: 'post'
    }
    let fileMessage = {
      fileType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      fileName: '已归档列表',
      fileExt: 'xlsx'
    }
    await downloadFileTemplate(ajaxConfig, fileMessage, () => { message.success('获取成功') })
  }

  /**
   *
   * 创建每个表单项
   * @param {*} toggleButton 判断是否为切换更多的按钮
   * @memberof SearchForm
   */
  createFormItems = (toggleButton) => {
    const { pub_isLoading, renderFormItems, formItems, searchButtonText, withPrint, pub_allTableData } = this.props;
    // newformItems用来设置新的搜索框格式
    let newformItems;
    if (this.state.setSearchState) {
      newformItems = {
        ajaxConfig: formItems.ajaxConfig,
        formItems: [...formItems.formItems, ...formItems.moreFormItems]
      }
    } else {
      newformItems = formItems
    }
    // 根据配置生成
    let formItemList = renderFormItems(newformItems, this.formRef.current, searchButtonText, this.handleSumbit, withPrint ? this.handlePrint : null);
    this.setState({ formItemList }, () => {
      // 判断一下先前有没有数据，如果有则重新渲染所选页，没有则重新渲染
      if (pub_isLoading[this.markId] === undefined) {
        this.handleSumbit()
      } else {
        if (toggleButton) return;
        const { pageSize = 10, page } = pub_allTableData[this.markId] || {}
        this.handleSumbit({ size: pageSize, page })
      }
    })
  }
  /**
   * @description: 用于表单搜集完数据后发送请求的函数
   * @param {object} ajaxConfig ajax配置
   * @param {*} data // 请求参数
   * @return:
   */
  searchFunc = (ajaxConfig, data) => { // 请求后台表格数据，发送请求时应该先请求第一页数据
    let { ajaxType, data: searchData, url, ContentType = 'application/json' } = ajaxConfig;
    //searchAddPagination已经配置好默认请求第一页了
    let option = {
      type: ajaxType,
      url,
      data: Object.assign({}, searchData, data),
      headers: {
        'Content-Type': ContentType // 默认是'application/json'
      }
    }
    sessionStorage.setItem('pubSearchConfig', JSON.stringify(data))
    return _fetch(option)
  }
  searchAddPagination = (values, searchValue) => {  // 增加分页的条件
    let search = _.cloneDeep(values);
    // 有值传入时即为刷新页面，没有则重新渲染
    if (searchValue?.page) {
      search.page = searchValue.page;
      search.size = searchValue.size
    } else {
      const { fixedConf: { size } } = this.props;
      search.page = 1; // 现在默认每一次点击搜索都是默认搜索第一页,后台字段是page
      search.size = size || Number(sessionStorage.getItem('tableHeight')) > 950 ? 20 : 10;
    }
    return search;
  }

  // 返回获取到的表格数据，搜索时可用
  returnAllTableData = async (searchData) => {
    const { formItems: { ajaxConfig }, getAllTableData, changeTableData, pub_changeisLoading } = this.props;
    pub_changeisLoading(true, this.markId); //先置为true
    try {
      let result = await this.searchFunc(ajaxConfig, searchData); // 如果是搜索的话，就传搜索条件data
      if (result.data.success === false) {
        throw new Error()
      }

      let tableData = {}
      if (result && result.data.data) {
        tableData = changeTableData(result.data.data) // 调用父组件传来的changeTableData，修改获得的表格的数据成符和格式的数据
        let Data = _.cloneDeep(tableData); // 深拷贝一份数据
        Data.data.forEach((item) => { // 让每一个表格数据都获得key
          item.key = item.id ? item.id : item.stuId;
        })
        Data.pageData = { // 配置表格的页码器
          pageSize: Data.size || 10,
          current: Data.page || 1,
          total: Data.total,
        }
        pub_changeisLoading(false, this.markId); // 获取到数据就置为false
        getAllTableData(Data, this.markId); // 把表格数据发送到store
      }
    } catch (err) {
      pub_changeisLoading(false, this.markId); // 获取到数据就置为false
      message.error('表格请求错误')
    }
  }

  componentDidUpdate({ formItems }) {
    if (JSON.stringify(formItems) !== JSON.stringify(this.props.formItems)) {
      this.createFormItems();
    }
  }

  render() {
    const { style, name, formItems, checkedChildren, unCheckedChildren, switchCallback } = this.props
    return (
      <div
        style={{ ...style }}
      >
        <Form
          name={name}
          ref={this.formRef}
          className="search-form"
          onFinish={() => {
            this.handleSumbit()
          }}
        >
          {formItems?.moreFormItems &&
            <Form.Item>
              <Switch
                checkedChildren={checkedChildren || "更多"}
                unCheckedChildren={unCheckedChildren || "普通"}
                checked={this.state.setSearchState}
                // change后回调
                onChange={(checked) => {
                  this.setState({ setSearchState: checked }, () => {
                    this.createFormItems(true)
                    switchCallback?.(checked)
                  })
                }}
              />
            </Form.Item>}
          {this.state.formItemList}
        </Form>
      </div>
    )
  }
}

SearchForm.propTypes = {
  changeSearchLimit: PropTypes.func, // 增加修改限制
  changeTableData: PropTypes.func, // 修改表格数据
}

@connect(mapStateToProps, mapDispatchToProps) // 装饰器
@withRouter
@UtilsHOC
class SearchFormRef extends Component {
  render() {
    return (<SearchForm {...this.props} ref={this.props.myForwardedRef} />) // 转发ref，不然拿到的是connect高阶组件的ref
  }
}
export default forwardRef((props, ref) => {
  return <SearchFormRef {...props} myForwardedRef={ref} />
})
